/*
 * Created by SharpDevelop.
 * User: Dror B. Helper
 * Date: 01/10/2008
 * Time: 21:57
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Threading;
using StackOverflowClient.Messages;
using System.Net;

namespace StackOverflowClient
{
    public class ListnerParams
    {
        public ListnerParams(string url, IWebProxy proxy)
        {
            URL = url;
            Proxy = proxy;
        }
        internal string URL { get; set; }
        internal IWebProxy Proxy { get; set; }
    }

    /// <summary>
    /// Description of Listner.
    /// </summary>
    public class Listner
    {
        private readonly MessageQueue messageQueue = new MessageQueue();
        private readonly UserArchive archive = new UserArchive();
        private bool isAlive = true;
        private Thread pollingThread;
        private readonly int pollingInterval;

        public Listner(int pollingIntervalSec)
        {
            pollingInterval = pollingIntervalSec;
        }

        public void Run(ListnerParams parameters)
        {
            if (pollingThread != null)
            {
                Abort();
            }
            isAlive = true;
            pollingThread = new Thread(new ParameterizedThreadStart(DoWork));
            pollingThread.Start(parameters);
        }

        public void Abort()
        {
            isAlive = false;
            if (pollingThread != null)
            {
                if (pollingThread.Join(5000) == false)
                {
                    pollingThread.Abort();
                }
            }

            pollingThread = null;
        }

        private void DoWork(object parameters)
        {
            ListnerParams param = (ListnerParams)parameters;
            string infoUrl = param.URL;
            IWebProxy proxy = param.Proxy;

            while (isAlive)
            {
                Thread.Sleep(pollingInterval);

                try
                {
                    var urlString = HttpWebRequestExtension.GetStringFromURL(infoUrl.ToString(), proxy);
                    var userDescriptor = Parser.Parse(urlString);
                    Process(userDescriptor);
                }
                catch (Exception e)
                {
                    // TODO: report exception
                    // messageQueue.Enqueue(new ExceptionCaughtMessage(e));
                }
            }
        }

        internal void Process(UserDescriptor userDescriptor)
        {
            // Load user details
            var loadedUser = archive.Load(userDescriptor.Name);

            // Save new user descriptor 
            archive.Save(userDescriptor);

            // Check if changed from last time
            if (loadedUser == null)
            {
                return;
            }

            if (loadedUser.Reputation != userDescriptor.Reputation)
            {
                messageQueue.Enqueue(new ReputationChangedMessage(userDescriptor, loadedUser.Reputation, userDescriptor.Reputation));
            }
            
            if(loadedUser.NumberOfGoldBadges != userDescriptor.NumberOfGoldBadges)
            {
            	messageQueue.Enqueue(new NumberOfBadgesChangedMessage(userDescriptor, loadedUser.NumberOfGoldBadges, userDescriptor.NumberOfGoldBadges));
            }
            
        }

        public MessageQueue MessageQueue
        {
            get { return messageQueue; }
        }

        public UserDescriptor GetUserDetails(UserDescriptor userDescriptor)
        {
            try
            {
                if (archive.Exist(userDescriptor.Name))
                {
                    return archive.Load(userDescriptor.Name);
                }
            }
            catch (Exception)
            {
                //TODO: error reporting
            }

            archive.Save(userDescriptor);

            return userDescriptor;
        }

        public UserDescriptor IsValid(string userUrl, IWebProxy proxy)
        {
            try
            {
                var urlString = HttpWebRequestExtension.GetStringFromURL(userUrl.ToString(), proxy);

                if (string.IsNullOrEmpty(urlString))
                {
                    return null;
                }

                UserDescriptor userDescriptor = null;
                try
                {
                    userDescriptor = Parser.Parse(urlString);
                    if (string.IsNullOrEmpty(userDescriptor.Name))
                    {
                        return null;
                    }
                }
                catch (Exception)
                {
                    return null;
                }

                return userDescriptor;
            }
            catch (Exception)
            {
                return null;
            }
        }
    }

    internal class UserDescriptorMessage : MessageBase
    {
        public UserDescriptorMessage(UserDescriptor user)
            : base(user)
        {
        }
    }
}
